/*
 * Copyright (C) 2011 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.bkkit.redlung;

import java.util.Random;

import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;

public class BlockListener extends org.bukkit.event.block.BlockListener {
	private final static String SOURCE_NAME = BlockListener.class.getName();
	private final Random random;
	private final Config config;
	private final RadiatedPlayers radiatedPlayers;

	public BlockListener(final Config config,
			final RadiatedPlayers radiatedPlayers) {
		random = new Random();
		this.config = config;
		this.radiatedPlayers = radiatedPlayers;
	}

	@Override
	public void onBlockDamage(BlockDamageEvent event) {
		LogWrapper.entering(SOURCE_NAME, "onBlockDamage", event);
		if (!event.isCancelled()) {
			final Block block = event.getBlock();
			final BlockState state = block.getState();
			final Material material = state.getType();
			if (material == Material.GLOWING_REDSTONE_ORE) {
				radiatePlayer(event.getPlayer());
			}
		}
		LogWrapper.exiting(SOURCE_NAME, "onBlockDamage", event);
		super.onBlockDamage(event);
	}

	@Override
	public void onBlockBreak(final BlockBreakEvent event) {
		LogWrapper.entering(SOURCE_NAME, "onBlockBreak", event);
		if (!event.isCancelled()) {
			final Block block = event.getBlock();
			final BlockState state = block.getState();
			final Material material = state.getType();
			if (material == Material.REDSTONE_ORE
					|| material == Material.GLOWING_REDSTONE_ORE) {
				radiatePlayer(event.getPlayer());
			}
		}
		LogWrapper.exiting(SOURCE_NAME, "onBlockBreak", event);
		super.onBlockBreak(event);
	}

	private void radiatePlayer(final Player player) {
		LogWrapper.entering(SOURCE_NAME, "radiatePlayer", player);
		if (!playerWearingProtection(player.getInventory())) {
			final int radiationOdds = this.config.getRadiationOdds();
			LogWrapper.fine("Radiation odds: " + radiationOdds);
			if (radiationOdds > 0) {
				// Jump through some hoops to make sure random is not
				// concurrently accessed
				final boolean makeSick;
				synchronized (this.random) {
					makeSick = random.nextInt(radiationOdds) == 0;
				}
				if (makeSick) {
					makePlayerSick(player);
				}
			}
		}
		LogWrapper.exiting(SOURCE_NAME, "radiatePlayer", player);
	}

	private void makePlayerSick(final Player player) {
		LogWrapper.entering(SOURCE_NAME, "makePlayerSick", player);
		final String radiatedMessage = this.config.getRadiatedMessage();
		if ((radiatedMessage != null) && (radiatedMessage.length() > 0)) {
			LogWrapper.fine("Sending player message: " + radiatedMessage);
			player.sendMessage(radiatedMessage);
			this.radiatedPlayers.radiatePlayer(player);
		}
		LogWrapper.exiting(SOURCE_NAME, "makePlayerSick", player);
	}

	private boolean playerWearingProtection(final PlayerInventory inventory) {
		LogWrapper.entering(SOURCE_NAME, "playerWearingProtection", inventory);
		final ItemStack chestplateStack = inventory.getChestplate();
		final Material chestplateType = chestplateStack.getType();
		final boolean protection = chestplateType == Material.GOLD_CHESTPLATE;
		LogWrapper.fine("Player is " + (protection ? "" : "not ")
				+ "wearing protection");
		LogWrapper.exiting(SOURCE_NAME, "playerWearingProtection", inventory);
		return protection;
	}
}
